// $Id$
/*
 *  Copyright (C) 2007 NourY Solutions
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 3 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library. If not, see <http://www.gnu.org/licenses/>.
 *
 */
/*! \file
 * \brief Collection of exceptions.
 *
 * \author $Author$
 * \date $Date$
 * \version $Revision$
 */

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Security.Permissions;
#if (!NET_CF)
using System.Runtime.Serialization;
#endif

namespace Salamanca.Collections
{



    ///////////////////////////////////////////////////////////////////////////
    ///
    /// <summary>A collection of exceptions represented as a single exception.</summary>
    ///
    ///////////////////////////////////////////////////////////////////////////

#if (!NET_CF)
    [Serializable]
#endif
    public sealed class ExceptionCollection:
        Exception
    {

        /// <summary>Initializes a new instance of the <see cref="ExceptionCollection" /> class.</summary>
        /// <param name="exceptions">The collection of exceptions that this <see cref="ExceptionCollection" /> represents.</param>
        public ExceptionCollection(ICollection<Exception> exceptions):
            this(exceptions, null)
        {
        }

        /// <summary>Initializes a new instance of the <see cref="ExceptionCollection" /> class.</summary>
        /// <param name="exceptions">The collection of exceptions that this <see cref="ExceptionCollection" /> represents.</param>
        /// <param name="message">The message that describes the error. </param>
        public ExceptionCollection(ICollection<Exception> exceptions, string message):
            base(message)
        {
            Debug.Assert(exceptions!=null);
            if (exceptions==null)
                throw new ArgumentNullException("exceptions");
            Debug.Assert(exceptions.Count>0);
            if (exceptions.Count==0)
                throw new ArgumentException(Resources.SR.EmptyCollectionExceptionMessage, "exceptions");

            _Exceptions=new List<Exception>(exceptions);
        }



#if (!NET_CF)
        /// <summary>Initializes a new instance of the <see cref="ExceptionCollection"></see> class with serialized data.</summary>
        /// <param name="context">The <see cref="StreamingContext"></see> that contains contextual information about the source or destination.</param>
        /// <param name="info">The <see cref="SerializationInfo"></see> that holds the serialized object data about the exception being thrown.</param>
        /// <exception cref="SerializationException">The class name is null or <see cref="Exception.HResult"></see> is zero (0).</exception>
        /// <exception cref="ArgumentNullException">The info parameter is <c>null</c>.</exception>
        private ExceptionCollection(SerializationInfo info, StreamingContext context):
            base(info, context)
        {
            _Exceptions=(List<Exception>)info.GetValue("exceptions", typeof(List<Exception>));
        }

        /// <summary>Sets the <see cref="SerializationInfo"></see> with information about the exception.</summary>
        /// <param name="context">The <see cref="StreamingContext"></see> that contains contextual information about the source or destination.</param>
        /// <param name="info">The <see cref="SerializationInfo"></see> that holds the serialized object data about the exception being thrown.</param>
        /// <exception cref="ArgumentNullException">The info parameter is a null reference.</exception>
        [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.SerializationFormatter)]
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            Debug.Assert(info!=null);
            if (info==null)
                throw new ArgumentNullException("info");

            info.AddValue("exceptions", _Exceptions);
            base.GetObjectData(info, context);
        }
#endif



        /// <summary>Gets the list of exceptions that are part of the current exception.</summary>
        /// <returns>The list of exceptions that are part of the current exception.</returns>
        public ReadOnlyCollection<Exception> Exceptions
        {
            get
            {
                return new ReadOnlyCollection<Exception>(_Exceptions);
            }
        }

        /// <summary>Gets a message that describes the current exception.</summary>
        /// <returns>The error message that explains the reason for the exception, or an empty string("").</returns>
        public override string Message
        {
            get
            {
                if (_Exceptions.Count==1)
                    return _Exceptions[0].Message;

                return base.Message;
            }
        }

#if (!NET_CF)
        /// <summary>Gets or sets the name of the application or the object that causes the error.</summary>
        /// <returns>The name of the application or the object that causes the error.</returns>
        public override string Source
        {
            get
            {
                if (_Exceptions.Count==1)
                    return _Exceptions[0].Source;

                return base.Source;
            }
        }
#endif

        /// <summary>Gets a string representation of the frames on the call stack at the time the current exception was thrown.</summary>
        /// <returns>A string that describes the contents of the call stack, with the most recent method call appearing first.</returns>
        public override string StackTrace
        {
            get
            {
                if (_Exceptions.Count==1)
                    return _Exceptions[0].StackTrace;

                return base.StackTrace;
            }
        }



        /// <summary></summary>
        private List<Exception> _Exceptions;
    }
}
